package com.banfan.almond.web.config;


import org.apache.ibatis.jdbc.ScriptRunner;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.sql.*;

@Component
public class CreateDatabase {


    public static void main(String[] args) throws Exception {
//        executeSqlFile("D:\\Project\\JavaProject\\ForkProject\\almond_blog\\web\\src\\main\\resources\\static\\almond_blog.sql"
//        ,"localhost"
//        );
    }

    public static void executeSql(String sqlFilePath,
                                  String host,
                                  String port,
                                  String username,
                                  String password,
                                  String dataBaseName
                                  ) throws Exception {



        String JDBC_DRIVER = "com.mysql.jdbc.Driver";
        String DB_URL = "jdbc:mysql://"+host+":"+port+"/?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true";


        Exception error = null;
        // 获取连接对象
        Connection conn = DriverManager.getConnection(DB_URL, username, password);


        boolean existDatabase = isExistDatabase(dataBaseName, conn);
        if (existDatabase){
            System.out.println("存在数据库: " + existDatabase);
            System.out.println("不执行: " + sqlFilePath);
            return;
        }

        try {
            // 设置不自动提交
            conn.setAutoCommit(false);
            // 初始化ScriptRunner
            ScriptRunner runner = new ScriptRunner(conn);
            // 设置不自动提交
            runner.setAutoCommit(false);
            // true，遇见错误会停止执行，打印并抛出异常，捕捉异常，并进行回滚，保证在一个事务内执行；
            // false，遇见错误不会停止，会继续执行，会打印异常信息，并不会抛出异常，当前方法无法捕捉异常无法进行回滚操作，无法保证在一个事务内执行；
            runner.setStopOnError(true);
            // true则获取整个脚本并执行；
            // false则按照自定义的分隔符每行执行；
            runner.setSendFullScript(false);
            // 定义命令间的分隔符
            runner.setDelimiter(";");
            runner.setFullLineDelimiter(false);
            // 设置是否输出日志，null不输出日志，不设置自动将日志输出到控制台
            runner.setLogWriter(null);

            System.out.println("【执行sql文件】读取sql文件");
            // 读取文件

            ClassPathResource classPathResource = new ClassPathResource(sqlFilePath);
            InputStream inputStream =classPathResource.getInputStream();

            System.out.println("【执行sql文件】开始执行sql文件");
            // 如果有多个sql文件，可以写多个runner.runScript(xxx),
            runner.runScript(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            // 执行
            conn.commit();
            System.out.println("【执行sql文件】 成功");
        } catch (Exception e) {
            System.out.println("【执行sql文件】执行出错，开始回滚");
            conn.rollback();
            error = e;
        } finally {
            close(conn);
        }
        if (error != null) {
            throw error;
        }
    }

    public static void executeSqlFile(String sqlFileName,String HOST) throws Exception {

          String JDBC_DRIVER = "com.mysql.jdbc.Driver";
//          String HOST = "localhost";
        //    static final String HOST = "mysql";
          String DB_URL = "jdbc:mysql://"+HOST+":3306/?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true";
          String USER = "root";
          String PASS = "root";

        Exception error = null;
        // 获取连接对象
        Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
        String database = "almond_blog";

        boolean existDatabase = isExistDatabase(database, conn);
        System.out.println("isExist: " + existDatabase);
        if (existDatabase){
            return;
        }

        try {
            // 设置不自动提交
            conn.setAutoCommit(false);
            // 初始化ScriptRunner
            ScriptRunner runner = new ScriptRunner(conn);
            // 设置不自动提交
            runner.setAutoCommit(false);
            // true，遇见错误会停止执行，打印并抛出异常，捕捉异常，并进行回滚，保证在一个事务内执行；
            // false，遇见错误不会停止，会继续执行，会打印异常信息，并不会抛出异常，当前方法无法捕捉异常无法进行回滚操作，无法保证在一个事务内执行；
            runner.setStopOnError(true);
            // true则获取整个脚本并执行；
            // false则按照自定义的分隔符每行执行；
            runner.setSendFullScript(false);
            // 定义命令间的分隔符
            runner.setDelimiter(";");
            runner.setFullLineDelimiter(false);
            // 设置是否输出日志，null不输出日志，不设置自动将日志输出到控制台
            runner.setLogWriter(null);

            System.out.println("【执行sql文件】读取sql文件");
            // 读取文件

            ClassPathResource classPathResource = new ClassPathResource(sqlFileName);
            InputStream inputStream =classPathResource.getInputStream();

            System.out.println("【执行sql文件】开始执行sql文件");
            // 如果有多个sql文件，可以写多个runner.runScript(xxx),
            runner.runScript(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            // 执行
            conn.commit();
            System.out.println("【执行sql文件】 成功");
        } catch (Exception e) {
            System.out.println("【执行sql文件】执行出错，开始回滚");
            conn.rollback();
            error = e;
        } finally {
            close(conn);
        }
        if (error != null) {
            throw error;
        }
    }


    private static void close(Connection conn) {
        System.out.println("【执行sql文件】关闭数据库连接");
        try {
            if (conn != null) {
                conn.close();
            }
        } catch (Exception e) {
            if (conn != null) {
                conn = null;
            }
        }
    }

    public static boolean isExistDatabase(String database,Connection conn) throws Exception {
        Exception error = null;

        Statement stmt = null;
        ResultSet rs = null;// 数据库结果集

        stmt = conn.createStatement();
        String sql =String.format("SELECT COUNT(*) FROM information_schema.schemata WHERE schema_name=\"%s\"",database);
        rs = stmt.executeQuery(sql);
        if (rs.next()) {
            if (rs.getInt(1) == 0) {
                return false;
            } else {
                return true;
            }
        }
        return false;
    }

}

